#ifndef Archerbase_H_20120313
#define Archerbase_H_20120313

#include <list>
#include "InlineFunc.h"

struct MyPoint
{
    MyPoint(float _x, float _y)
    {
        x = _x;
        y = _y;
    }
    
    MyPoint()
    {
        x = 0;
        y = 0;
    }
    float x;
    float y;
};


#ifndef CC_DEGREES_TO_RADIANS
#define CC_DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) * 0.01745329252f) 
#endif


inline double multiply(MyPoint p1, MyPoint p2, MyPoint p0)

{
    
	return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));	
    
}

inline bool IsLineInsert(MyPoint ptLine1Begin, MyPoint ptLine1End,
						 MyPoint ptLine2Begin, MyPoint ptLine2End)
{
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
	return((max(ptLine1Begin.x,ptLine1End.x)>=min(ptLine2Begin.x,ptLine2End.x))&&

		(max(ptLine2Begin.x,ptLine2End.x)>=min(ptLine1Begin.x,ptLine1End.x))&&
		(max(ptLine1Begin.y,ptLine1End.y)>=min(ptLine2Begin.y,ptLine2End.y))&&
		(max(ptLine2Begin.y,ptLine2End.y)>=min(ptLine1Begin.y,ptLine1End.y))&&
		(multiply(ptLine2Begin,ptLine1End,ptLine1Begin)*multiply(ptLine1End,ptLine2End,ptLine1Begin)>=0)&&
		(multiply(ptLine1Begin,ptLine2End,ptLine2Begin)*multiply(ptLine2End,ptLine1End,ptLine2Begin)>=0));
#else
	return((std::max(ptLine1Begin.x,ptLine1End.x)>=std::min(ptLine2Begin.x,ptLine2End.x))&&
           
           (std::max(ptLine2Begin.x,ptLine2End.x)>=std::min(ptLine1Begin.x,ptLine1End.x))&&
           (std::max(ptLine1Begin.y,ptLine1End.y)>=std::min(ptLine2Begin.y,ptLine2End.y))&&
           (std::max(ptLine2Begin.y,ptLine2End.y)>=std::min(ptLine1Begin.y,ptLine1End.y))&&
           (multiply(ptLine2Begin,ptLine1End,ptLine1Begin)*multiply(ptLine1End,ptLine2End,ptLine1Begin)>=0)&&
           (multiply(ptLine1Begin,ptLine2End,ptLine2Begin)*multiply(ptLine2End,ptLine1End,ptLine2Begin)>=0));
#endif
}

const long INSERTRECT_NONE    = 0;
const long INSERTRECT_LEFT    = 1;
const long INSERTRECT_TOP     = 2;
const long INSERTRECT_RIGHT   = 3;
const long INSERTRECT_BOTTOM  = 4;

inline bool IsLineInsertSquare(MyPoint ptLineBegin, MyPoint ptLineEnd, MyPoint ptLeftUp, MyPoint ptRightBottom)
{
	long ret = 0;
	if(IsLineInsert(ptLineBegin, ptLineEnd, ptLeftUp, MyPoint(ptRightBottom.x, ptLeftUp.y)))
	{
		SetFlag(ret, INSERTRECT_TOP);
	}
	if(IsLineInsert(ptLineBegin, ptLineEnd, MyPoint(ptRightBottom.x, ptLeftUp.y), ptRightBottom))
	{
		SetFlag(ret, INSERTRECT_RIGHT);
	}
	if(IsLineInsert(ptLineBegin, ptLineEnd, ptRightBottom, MyPoint(ptLeftUp.x, ptRightBottom.y)))
	{
		SetFlag(ret, INSERTRECT_BOTTOM);
	}
	if(IsLineInsert(ptLineBegin, ptLineEnd, MyPoint(ptLeftUp.x, ptRightBottom.y), ptLeftUp))	
	{
		SetFlag(ret, INSERTRECT_LEFT);
	}
    
	return ret;
}


struct LineParam
{
    float _a;
    float _b;
    float _c;
};

inline void CalLineParam(MyPoint pt1, MyPoint pt2, LineParam &outParam)
{
    float k;
    if(::abs(pt1.x - pt2.x) < 0.001)
    {
        k = 1;
    }
    else
    {
        k = (pt1.y - pt2.y) / (pt1.x - pt2.x);
    }
    
    float b = pt1.y - k*pt1.x;
    
    if(k < 0)
    {
        outParam._a = -k;
        outParam._b = 1;
        outParam._c = -b;
    }
    else
    {
        outParam._a = k;
        outParam._b = -1;
        outParam._c = b;
    }
}

// 右侧 > 0 左侧 < 0  直线上 = 0;
inline int PointLineRelation(MyPoint ptLine1, MyPoint ptLine2, MyPoint ptJudge)
{
    LineParam lp;
    CalLineParam(ptLine1, ptLine2, lp);
    
    return (int)(ptJudge.x * lp._a + ptJudge.y * lp._b + lp._c);
}

// 击中位置
enum HitPositon
{
    ARCHER_HIT_HEAD,
    ARCHER_HIT_BODY,
    ARCHER_HIT_FOOT,
    ARCHER_HIT_NONE
};

// AABB盒
struct AABB
{
    MyPoint _ptLeftUp;
    MyPoint _ptRightBottom;
};


class CArcherBase
{
public:
    CArcherBase()
    :m_lastAngle(0)
    , m_curPower(0)
    , m_bFlip(false)
    , m_hp(100)
    {
        m_ptPos = MyPoint(0, 0);
    }
    
    float GetCurAngle()  {return m_lastAngle;}
	float GetPower()     {return m_curPower;}
    long  GetHP()        {return m_hp;}
    void  AddHp(long hp) {m_hp += hp;}
    void  SetHp(long hp) {m_hp = hp;}
    
    void  ResetHurtPos() {m_hurtPos = ARCHER_HIT_NONE;}
    
    virtual void SetPos(const MyPoint &ptPos);
    MyPoint GetPos() const {return m_ptPos;}
    
    void UpdateAABB();
    
    // 是否被打中，碰撞检测
    HitPositon   IsHitted(MyPoint ptStart, MyPoint ptEnd);
    // 被打中进行结算
    virtual void Hitted(HitPositon pos, MyPoint ptHurt);

protected:
    int        m_id;
    MyPoint     m_ptPos;      
    bool       m_bFlip;       // 是否翻转，当角色在右侧时，为true
    long       m_hp;
    HitPositon m_hurtPos;     // 受伤位置
    float      m_maxAngle;    // 最大仰角
    float      m_minAngle;    // 最小仰角
    AABB                 m_aabbHeadOrg;    // AABB原始信息
    AABB                 m_aabbBodyOrg;
    AABB                 m_aabbFootOrg;
    
    
    float m_lastAngle;                      // 上次射箭角度
	float m_curPower;                       // 当前力量
    AABB                 m_aabbHead;       // AABB当前信息
    AABB                 m_aabbBody;
    AABB                 m_aabbFoot;
    
    
    
    std::list<CArcherBase *>     m_listTarget;
};

class CArrowBase
{
public:
	CArrowBase()
    : m_startPower(0)
    , m_gravity(1500)
    , m_curWindPower(0)
    , m_mass(2.0f)
    , m_pListTarget(NULL)
	{
        
	}
    
	MyPoint GetStartPos() {return m_ptStartPos;}
	MyPoint GetCurPos()   {return m_ptCur;}
    
    
	// 设置初始参数，应该再构造后调用
	void SetParam(float mass, float gravity, float windPower, float arrowWidth);
	// 发射时调用
	void Shoot(float power, MyPoint ptHead, float angle, std::list<CArcherBase *> *pTargetList);
    // 循环，time 从零增加
	bool ProcessLogicTime(float time);
    
protected:
	MyPoint             m_ptCur;         // 当前位置，逻辑坐标
    
	MyPoint             m_ptStartPos;   // 射出时箭头坐标
	float              m_startPower;   // 射出时初始力量
	float              m_startRad;     // 射出时初始弧度
    
	float              m_mass;          // 质量
	float              m_gravity;       // 重力加速度
	float              m_curWindPower;  // 风力
    
	float              m_arrowWidth;
    
	std::list<CArcherBase *>   *m_pListTarget;
    
};

#endif